<?php

/**
 * export class - Template - Export canvas as XML file
 */

namespace Leantime\Domain\Canvas\Controllers {

    use Exception;
    use Illuminate\Contracts\Container\BindingResolutionException;
    use Illuminate\Support\Str;
    use Leantime\Core\Configuration\Environment as EnvironmentCore;
    use Leantime\Core\Controller\Controller;
    use Leantime\Core\Language as LanguageCore;
    use Leantime\Domain\Projects\Repositories\Projects as ProjectRepository;
    use Symfony\Component\HttpFoundation\Response;

    /**
     * Template class For exporting class as XML file
     */
    class Export extends Controller
    {
        /**
         * Constant that must be redefined
         */
        protected const CANVAS_NAME = '??';

        protected const CANVAS_TYPE = 'canvas';

        // Internal variables
        protected EnvironmentCore $config;

        protected LanguageCore $language;

        protected mixed $canvasRepo;

        protected array $canvasTypes;

        protected array $statusLabels;

        protected array $relatesLabels;

        protected array $dataLabels;

        /***
         * Constructor
         */
        public function init(
            EnvironmentCore $config,
            LanguageCore $language,
        ) {

            $this->config = $config;
            $this->language = $language;
            $canvasName = Str::studly(static::CANVAS_NAME).static::CANVAS_TYPE;
            $repoName = app()->getNamespace()."Domain\\$canvasName\\Repositories\\$canvasName";
            $this->canvasRepo = app()->make($repoName);

            $this->canvasTypes = $this->canvasRepo->getCanvasTypes();
            $this->statusLabels = $this->canvasRepo->getStatusLabels();
            $this->relatesLabels = $this->canvasRepo->getRelatesLabels();
            $this->dataLabels = $this->canvasRepo->getDataLabels();
        }

        /**
         * run - Generate XML file
         */
        public function run(): Response
        {
            // Retrieve id of canvas to print
            if (isset($_GET['id']) === true) {
                $canvasId = (int) $_GET['id'];
            } elseif (session()->exists('current'.strtoupper(static::CANVAS_NAME).'Canvas')) {
                $canvasId = session('current'.strtoupper(static::CANVAS_NAME).'Canvas');
            } else {
                return new Response;
            }

            // Generate XML code
            $exportData = $this->export($canvasId);

            // Service report
            clearstatcache();
            $response = new Response($exportData);
            $response->headers->set('Content-type', 'application/xml');
            $response->headers->set('Content-Disposition', 'attachment; filename="'.static::CANVAS_NAME.static::CANVAS_TYPE.'-'.$canvasId.'.xml"');
            $response->headers->set('Cache-Control', 'no-cache');

            return $response;
        }

        /***
         * export - Generate XML file
         *
         * @access protected
         * @param int $id Canvas identifier
         * @return string XML data
         * @throws BindingResolutionException
         */
        protected function export(int $id): string
        {

            // Retrieve canvas data
            $canvasAry = $this->canvasRepo->getSingleCanvas($id);
            ! empty($canvasAry) || throw new Exception("Cannot find canvas with id '$id'");
            $projectId = $canvasAry[0]['projectId'];
            $recordsAry = $this->canvasRepo->getCanvasItemsById($id);
            $projectsRepo = app()->make(ProjectRepository::class);
            $projectAry = $projectsRepo->getProject($projectId);
            ! empty($projectAry) || throw new Exception("Cannot retrieve project id '$projectId'");

            // Generate XML data
            $xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>'.PHP_EOL.PHP_EOL;
            $xml .= $this->xmlExport(static::CANVAS_NAME.static::CANVAS_TYPE, $canvasAry[0]['title'], $recordsAry);

            return $xml;
        }

        /**
         * xmlExport - Generate XML for specific data
         *
         * @param  string  $canvasKey  Encoded canvas name
         * @param  array  $recordsAry  Array of canvas entry records
         * @param  int  $indent  Indent level to use;
         * @return string XML data
         */
        protected function xmlExport(string $canvasKey, string $canvasTitle, array $recordsAry, int $indent = 0): string
        {
            $is = str_repeat(' ', 4 * $indent);
            $tab = str_repeat(' ', 4);
            $xml = $is.'<canvas key="'.$canvasKey.'">'.PHP_EOL;
            $xml .= $is.$tab.'<title>'.$canvasTitle.'</title>'.PHP_EOL;
            $xml .= $is.$tab.'<content>'.PHP_EOL;

            foreach ($this->canvasTypes as $key => $data) {
                $xml .= $is.$tab.$tab.'<element key="'.$key.'">'.PHP_EOL;

                foreach ($recordsAry as $record) {
                    if ($record['box'] === $key) {
                        $xml .= $is.$tab.$tab.$tab.'<item>'.PHP_EOL;
                        $xml .= $is.$tab.$tab.$tab.$tab.'<created>'.($record['created'] ?? '').'</created>'.PHP_EOL;
                        $xml .= $is.$tab.$tab.$tab.$tab.'<modified>'.($record['modified'] ?? '').'</modified>'.PHP_EOL;
                        $xml .= $is.$tab.$tab.$tab.$tab.'<author id="'.$record['author'].'" firstname="'.($record['authorFirstname'] ?? '').'" '.
                             'lastname="'.($record['authorLastname'] ?? '').'"/>'.PHP_EOL;

                        $xml .= $is.$tab.$tab.$tab.$tab.'<description>'.($record['description'] ?? '').'</description>'.PHP_EOL;
                        $xml .= $is.$tab.$tab.$tab.$tab.'<status key="'.($record['status'] ?? '').'" />'.PHP_EOL;
                        $xml .= $is.$tab.$tab.$tab.$tab.'<relates key="'.($record['relates'] ?? '').'" />'.PHP_EOL;
                        $xml .= $is.$tab.$tab.$tab.$tab.'<assumptions>'.($record['assumptions'] ?? '').'</assumptions>'.PHP_EOL;
                        $xml .= $is.$tab.$tab.$tab.$tab.'<data>'.($record['data'] ?? '').'</data>'.PHP_EOL;
                        $xml .= $is.$tab.$tab.$tab.$tab.'<conclusion>'.($record['conclusion'] ?? '').'</conclusion>'.PHP_EOL;
                        $xml .= $is.$tab.$tab.$tab.'</item>'.PHP_EOL;
                    }
                }

                $xml .= $is.$tab.$tab.'</element>'.PHP_EOL;
            }
            $xml .= $is.$tab.'</content>'.PHP_EOL;
            $xml .= $is.'</canvas>'.PHP_EOL;

            return $xml;
        }
    }
}
